/*
 * CVImage.cpp
 *
 *  Created on: Nov 10, 2008
 *      Author: brain
 */

#include "CVImage.h"


CVImage::CVImage(IplImage * im)
{
	_counter=new RefCount(im);
}


CVImage::~CVImage()
{
	_counter->decrease();
}
CVImage::CVImage(CVImage & p)
{
    *this=p;
}

CVImage& CVImage::operator=(CVImage& cvi)
{
	if(cvi._counter!=this->_counter)
	{
		this->_counter->decrease();
		this->_counter=cvi._counter;
		this->_counter->increase();
	}
	return *this;
}
CVImage& CVImage::operator=(CVImage* cvi)
{
	if(cvi->_counter!=this->_counter)
	{
		this->_counter->decrease();
		this->_counter=cvi->_counter;
		this->_counter->increase();
	}
	return *this;
}
void CVImage::SaveAs(string filename)
{
	cvSaveImage(filename.c_str(),(FROM_32S_TO_8U()).ToIplImage());
}
void CVImage::ShowImage(string title)
{
	cvNamedWindow( title.c_str(), 1);
	cvShowImage( title.c_str(), (FROM_32S_TO_8U()).ToIplImage());
	cvWaitKey();
}
int CVImage::Pixel(uint x,uint y,uchar channel)
{
	return *((int*)Pix(x,y,channel));
}

void* CVImage::Pix(uint x,uint y,uchar channel)
{
	return (void *)(_counter->ImData()+(step()*y+(depth()>>3)*(x*channels()+channel)));
}
void* CVImage::Pix(uint index,uchar channel)
{
	return (void *)(_counter->ImData()+(index*channels()+channel)*(depth()>>3));
}

IplImage* CVImage::ToIplImage()
{
	return _counter->_data;
}

const IplImage* CVImage::ToIplImage() const
{
	return _counter->_data;
}


CVImage CVImage::FROM_32S_TO_8U()
{
    assert(_counter!=0);
    if (DEBUG)
    {
        cout<< "channels: "<< (int)channels() <<endl;
    }
//	uchar c,*npix;
//	int opix;
//	uint x,y;
	CVImage un(cvCreateImage(cvSize(this->width(),this->height()),IPL_DEPTH_8U, channels()));
//	for(c=0;c< channels();c++)
//	{
//		for(x=0;x<width();x++)
//		{
//			for(y=0;y<height();y++)
//			{
//				opix=Pixel(x,y,c);
//				npix=(uchar*)un.Pix(x,y,c);
//				*npix=(uchar)opix;
//			}
//		}
//	}
//	if (DEBUG)
//		cout<< "conversion completed"<<endl;

    cvNormalize(*this,un,0,255,CV_MINMAX);




    return un;
}



void CVImage::ToGrayscale()
{
    assert(_counter!=0);
    if (DEBUG)
    {
        cout<< "channels: "<< (int)channels() <<endl;
    }

	if(_counter->_data->nChannels==3)
	{
		CVImage gray(cvCreateImage(cvSize(this->width(),this->height()),this->depth(), 1));
		cvCvtColor(_counter->_data,gray._counter->_data,CV_RGB2GRAY);
		*this=gray;
		if (DEBUG)
            cout<< "conversion completed"<<endl;
	}
}
template<class integer>
void CVImage::pclear(integer value)
{
	uint i;
	integer* data=reinterpret_cast<integer*>(_counter->_data->imageData);
	for (i=0;i<size()/(depth()>>3);i++)
	{
		data[i]=value;
	}
}

void CVImage::clear(int value)
{

	int dpth=encdepth();
	switch(dpth)
	{
		case IPL_DEPTH_1U:
			pclear<uchar>((uchar)value);
			break;
		case IPL_DEPTH_8S:
			pclear<char>((char)value);
			break;
		case IPL_DEPTH_8U:
			pclear<uchar>((uchar)value);
			break;
		case IPL_DEPTH_16S:
			pclear<short>((short)value);
			break;
		case IPL_DEPTH_16U:
			pclear<ushort>((ushort)value);
			break;
		//case IPL_DEPTH_32F:
			//break;
		case IPL_DEPTH_32S:
			pclear<int>(value);
			break;
		default:
			cout<<"unsupported image type"<<endl;
	}
}
inline CvScalar CVImage::getpix(uint x,uint y)
{
	return cvGet2D(_counter->_data,x,y);
}
inline void CVImage::setpix(uint x,uint y,CvScalar s)
{
	cvSet2D(_counter->_data,x,y,s);

}

uint CVImage::step() const
{
	return _counter->_data->widthStep;
}
uint CVImage::size() const
{
	return _counter->_data->imageSize;
}
uint CVImage::height() const
{
	return _counter->_data->height;
}
uint CVImage::width() const
{
	return _counter->_data->width;
}
uint CVImage::ibits() const
{
	return _counter->color_bits;
}
unsigned char CVImage::channels() const
{
	return _counter->_data->nChannels;
}
int CVImage::encdepth() const
{
	return _counter->_data->depth;
}
uint CVImage::depth() const
{
	return _counter->depth();
}

